<?php

class Cart
{
	private $srcModel;
	public $sections = array(
		'shop' => array(
			'source'	=> 'directory',
			'isDigital'	=> false,
		),
		'beats' => array(
			'source'	=> 'directory',
			'isDigital'	=> true,
		),
	);


	/**
	 * @var  array Website settings
	 **/
	protected $settings = array();

	/**
	 * @var  array  Class instances.
	 */
	protected static $instance;

	/**
	 * Returns an instance of Auth class by the given session id.
	 *
	 * @return  Auth
	 */
	public static function getInstance()
	{
		if (null == self::$instance) {
			self::$instance = new self();
		}
		return self::$instance;
	}

	public static function instance()
	{
		if (null == self::$instance) {
			self::$instance = new self();
		}
		return self::$instance;
	}

	/**
	 * Consrtuctor.
	 *
	 * @return  Auth
	 */
	public function __construct()
	{
		$this->init();
	}

	private function init()
	{
		$settings = Database::instance()->query('SELECT * FROM `settings`')->fetchAll();
		$values = array();
		foreach ($settings as $setting) {
			$this->settings[$setting['key']] = $values[$setting['key']] = $setting['value'];
		}
		unset($settings);
		$this->db = Database::instance();
		$this->model = Model::factory('cart');
	}

	public function setPaid($orderId)
	{
		if ($order = $this->model->getOrder($orderId)) {
			if ($order['isPaid'] == 0 || $order['subscriptionPeriod']) {
				Model_Table::instance('cartOrders')->update(array(
					'dateTimePaid' => date('Y-m-d H:i:s'),
					'isPaid' => 1,
				), (int)$orderId);
				$items = $this->model->getOrderItems($orderId);
				foreach ($items as $item) {
					try {
						$class = new ReflectionClass(ucfirst($item['source']) == 'Directory' ? 'DirectoryClass' : ucfirst($item['source']));
						$controller = $class->newInstance();
						if ($class->getMethod('setPaid')) {
							$controller->setPaid($item);
						}
					} catch (ReflectionException $e) {
						continue;
					}
				}
				$this->notifyOrderPaid($orderId);
			}
		}
	}

	private function notifyOrderPaid($orderId)
	{
		if (($order = $this->model->getOrder($orderId))) {
			$msg = '' . "\n";
			$msg .= 'Hello!' . "\n\n";
			$msg .= 'Order #' . $order['token'] . ' for $' . $order['amount'] . ' is paid.' . "\n\n";
			$msg .= 'Login to the system and view details in control panel.' . "\n";
			Mailer::sendMail($this->settings['email'], 'Order completed', $msg,$_SERVER['HTTP_HOST'].'<noreply@'.$_SERVER['HTTP_HOST'].'>');
		}
	}

	public function createOrder($order)
	{
		if (!isset($_SESSION)) {
			session_start();
		}
		$values = array();
		$values['sessionId'] = session_id();
		$cnt = 0;
		Model_Table::instance('cartOrders')->keys['string'] = 'token';
		while (true === Model_Table::instance('cartOrders')->exists(($token = System::random('alphanuml', 6))) && $cnt < 3) {
			$cnt++;
		}
		$values['token'] = $token;
		$delivery = (isset($order['order']['delivery']) ? $order['order']['delivery'] : false);
		$discount = (isset($order['order']['discount']) ? $order['order']['discount'] : 0);
		$values['amount'] = $this->getAmount($order['items'], $delivery, $discount);
		$values['dateTimeAdded'] = date('Y-m-d H:i:s');

		foreach ($order['order'] as $k => $v) {
			if ($k == 'delivery' && $order['order'][$k]) {
				$values['delivery'] = 1;
				$values['deliveryCost'] = $v;
			} elseif($k == 'discount') {
                                if($v == false) {
                                    $values['discount'] = NULL;
                                } else {
                                    $values['discount'] = $v['alias'];
                                }
                        } else {
                                $values[$k] = $v;
			}
		}

		foreach ($order['customer'] as $k => $v) {
			$values[$k] = $v;
		}
		$orderId = Model_Table::instance('cartOrders')->insert($values);
		$values = array();
		$values['orderId'] = $orderId;
		//system::dump($order['items'],1);
		foreach ($order['items'] as $item) {
			//system::dump($order,1);
			$values['itemId'] = $item['id'];
			$values['itemName'] = $item['name'];
			$values['source'] = $item['source'];
			$values['price'] = $item['price'];
			//$values['color'] = $item['color'];
			//$values['size2'] = $item['size'];
			$values['note'] = (isset($item['note']) ? $item['note'] : null);
			$values['section'] = (isset($item['section']) ? $item['section'] : null);
			$values['quantity'] = (isset($item['quantity']) ? $item['quantity'] : 1);
			//$values['size'] = (isset($item['settings']['size']) ? $item['settings']['size'] : NULL);
			//$values['type'] = (isset($item['settings']['color']) ? $item['settings']['color'] : NULL);
			$values['size'] = $item['size'];
			$values['type'] = $item['color'];
			Model_Table::instance('cartItems')->insert($values);
		}
		if ($orderId) {
			return $orderId;
		} else {
			Throw(new Exception('Error occured. Please, contact to administrator.'));
		}
	}

	private function getPaypalLink($orderId)
	{
		if (!($order = $this->model->getOrder($orderId))) {
			return null;
		}
		if ($this->settings['isSandbox']) {
			$link = 'https://www.sandbox.paypal.com/cgi-bin/webscr?';
		} else {
			$link = 'https://www.paypal.com/cgi-bin/webscr?';
		}
		$link .= 'cmd=_xclick&';
		$link .= 'business=' . urlencode($this->settings['paypalEmail']) . '&';
		$link .= 'item_name=' . urlencode('Your order from ' . $this->settings['title']) . '&';
		$link .= 'item_number=' . urlencode($order['token']) . '&';
		if ($order['delivery']) {
			$link .= 'shipping=' . urlencode($this->settings['delivery']) . '&';
		}
		$link .= 'amount=' . urlencode($order['amount']) . '&';
		$link .= 'no_shipping=0&';
		$link .= 'no_note=1&';
		$link .= 'currency_code=USD&';
		$link .= 'lc=US&';
		$link .= 'rm=2&';
		$link .= 'notify_url=' . urlencode(Url::site('/commerce/ipn/'));
		return $link;
	}

	private function getPaypalSubscriptionLink($orderId)
	{
		if (!($order = $this->model->getOrder($orderId))) {
			return null;
		}
		if ($this->settings['sandbox']) {
			$link = 'https://www.sandbox.paypal.com/cgi-bin/webscr?';
		} else {
			$link = 'https://www.paypal.com/cgi-bin/webscr?';
		}
		$link .= 'cmd=_xclick-subscriptions&';
		$link .= 'business=' . urlencode($this->settings['paypalEmail']) . '&';
		$link .= 'item_name=' . urlencode('Subsctiption from ' . $this->settings['title']) . '&';
		$link .= 'invoice=' . urlencode($order['token']) . '&';
		$link .= 'a3=' . urlencode($order['amount']) . '&';
		$link .= 'p3=' . urlencode($order['subscriptionPeriod']) . '&';
		$link .= 't3=M&';
		$link .= 'src=1&';
		$link .= 'no_shipping=0&';
		$link .= 'no_note=1&';
		$link .= 'currency_code=USD&';
		$link .= 'lc=US&';
		$link .= 'rm=2&';
		$link .= 'notify_url=' . urlencode(Url::site('/commerce/ipn/'));
		return $link;
	}

	public function callbackModules($orderId)
	{
		$order = $this->model->getOrder($orderId);
		if ($order['isPaid']) {
			$items = $this->model->getOrderItems($orderId);
			foreach ($items as $source => $items) {
				try {
					$class = new ReflectionClass(ucfirst($item['source']) == 'Directory' ? 'DirectoryClass' : ucfirst($item['source']));
					$controller = $class->newInstance();
					try {
						$class->getMethod('getPaid')->invokeArgs($controller, $items);
					} catch (ReflectionException $e) {
					}
				} catch (ReflectionException $e) {
					throw new NotFoundException(ucfirst($e));
				}
			}
		}
	}
	public function validateItems($cartSection = null)
	{
		if (!isset($_SESSION)) {
			session_start();
		}
		$validItems = array();
		$items = array();
		if (isset($_SESSION['cart']) ? count($_SESSION['cart']) : false) {
			foreach ($_SESSION['cart'] as $section => $cartItems) {
				if ($cartSection ? $cartSection == $section : true) {
					foreach ($cartItems as $cartItem) {
						if (isset($this->sections[$section])) {
							$items[] = array_merge(array('source' => $this->sections[$section]['source']), $cartItem);
						}
					}
				}
			}
		}
		foreach ($items as $item) {
			
			try {
				$class = new ReflectionClass(ucfirst($item['source']) == 'Directory' ? 'DirectoryClass' : ucfirst($item['source']));
				$controller = $class->newInstance();
				if ($class->getMethod('validateItem')) {
					if (false !== ($result = $controller->validateItem($item))) {
						$validItems[] = array_merge(array('source' => $item['source'], 'quantity' => $item['quantity'], 'token' => $item['token'],'color' => $item['color'],'size' => $item['size']), $result);
					}
				}
			} catch (ReflectionException $e) {
				continue;
			}
		}
		return $validItems;
	}
	public function isDigital($items)
	{
		$isDigital = true;
		if (count($items)) {
			foreach ($items as $item) {
				$isDigital &= $this->sections[$item['section']]['isDigital'];
			}
		}
	return $isDigital;
	}
		public function getAmount($items, $delivery = false, $discount = 0) {
                    
		$result = 0;
		foreach ($items as $item) {
			$result += (round(((float)$item['price'] * (int)(isset($item['quantity']) ? $item['quantity'] : 1)) * 100) / 100);
		}
                if(is_array($discount)) {
                    $result = ($discount['type'] == 'percentage')?($result - $result*$discount['price']/100):($result - $discount['price']);
                }
		if ($delivery) {
			$result = $result + $delivery;//$this->settings['deliveryCost'];
		}
                if ($result <= 0) {
			$result = .01;
		}
//                    $result = $result - 99;
                if(isset($_SESSION['identity']['bonus_new_amount'])){
                    $result = $result - $_SESSION['identity']['bonus_new_amount'];
                }
		return $result;
	}
}